#ifndef GAMEBOARD_H
#define GAMEBOARD_H

#include <QObject>
#include <QColor>
#include <QList>
#include <QPoint>
#include <QMutex>
class GameBoard :  public QObject
{
  Q_OBJECT
  public:
    struct Choice;
    enum TILE_COLOR {RED=0, GREEN, BLUE, YELLOW, MAGENTA, ORANGE, CYAN, MAX_TILE_COLOR, BLACK};

    GameBoard(int width, int height, int numColors);
    GameBoard(const GameBoard &copy);
    const GameBoard& operator=(const GameBoard& rhs);

    virtual ~GameBoard();
    void lock();
    void unlock();
    int rows() const;
    int cols() const;
    void generate();
    void generate(int width, int height, int numColors);
    void load(const QString& file);
    bool isValidPosition(const QPoint& pos) const;
    // Will call removeSameNeighbors IF the clicked tile has at least one neighbor with the same color as it.
    // Returns the number of tiles left after the click(used for heuristics)
    unsigned int clickAt(const QPoint& pos);
    // Will mark cells as black.  Size will be the size of the glob of cells in this space (used for heuristics)
    void removeSameNeighbors(const QPoint& pos, TILE_COLOR col, unsigned int &size);
    void repositionTiles();
    bool checkForLose();
    unsigned int getRemainingTiles();
    unsigned int getRemainingTiles(TILE_COLOR col);
    unsigned int getNumSingletons();
    const QList< QList<TILE_COLOR> >& getBoard() const;
    QList<Choice> getChoiceList() const;

    static QColor colorFromTileColor(TILE_COLOR color);

  signals:
    void modified();
    void lose();
    void win();

  protected:
    // The below two functions are helper functions that determine if every tile
    // above or to the right of the given point is black.  Used to speed up
    // the repositionTiles method.
    bool allAboveBlack(const QPoint& pos) const;
    bool allRightBlack(const QPoint& pos) const;

  protected:
    QMutex mLock;
    int mWidth, mHeight, mNumColors;
    QList< QList<TILE_COLOR> > mTiles;
};

class GameBoard::Choice
{
  public:
    Choice(int row, int col, int rmbl, float score=0.0);
    bool operator<(const Choice& rhs) const;

    int mRow, mColumn, mRemovedBlocks;
    float mScore;
};

#endif // GAMEBOARD_H
